package com.vegetable.modules.service.outbound.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.vegetable.common.constant.CommonConstant;
import com.vegetable.common.utils.Constant.StockFlowType;
import com.vegetable.modules.entity.baseData.ProductSpec;
import com.vegetable.modules.entity.baseData.Products;
import com.vegetable.modules.entity.inbound.OrderCost;
import com.vegetable.modules.entity.outbound.*;
import com.vegetable.modules.entity.outbound.po.AllocationInAddPO;
import com.vegetable.modules.entity.outbound.po.AllocationOrderAddPO;
import com.vegetable.modules.entity.outbound.po.AllocationOrderQueryPO;
import com.vegetable.modules.entity.outbound.po.AllocationOutAddPO;
import com.vegetable.modules.mapper.outbound.AllocationOrderMapper;
import com.vegetable.modules.service.baseData.IProductSpecService;
import com.vegetable.modules.service.baseData.IProductsService;
import com.vegetable.modules.service.inbound.IAllocationInService;
import com.vegetable.modules.service.inbound.IOrderCostService;
import com.vegetable.modules.service.outbound.*;
import com.vegetable.modules.service.stock.IStockService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.List;

/**
 * <p>
 * 销售订货 服务类
 * </p>
 *
 * @author wangruijie
 * @since 2024-03-27
 */
@Slf4j
@Service
public class AllocationOrderServiceImpl extends ServiceImpl<AllocationOrderMapper, AllocationOrder> implements IAllocationOrderService {
    @Autowired
    // 商品规格
    private IProductSpecService specService;
    @Autowired
    private IStockService stockService;
    @Autowired
    private IOrderCostService orderCostService;
    @Autowired
    private IAllocationInService iAllocationInService;
    @Autowired
    private IAllocationOutService iAllocationOutService;
    @Autowired
    private IAllocationInDetailService iAllocationInDetailService;
    @Autowired
    private IAllocationOutDetailService iAllocationOutDetailService;
    @Autowired
    private IAllocationOrderDetailService iAllocationOrderDetailService;
    @Autowired
    private IProductsService productsService;
    /**
     * 新增调拨订单
     * @param po
     * @return
     */
    @Transactional
    public int addOrder(AllocationOrderAddPO po){
        List<AllocationOrderDetail> commodities = po.getCommodities();
        Integer totalNumber = commodities.stream().mapToInt(flow -> flow.getNumber()).sum();
        AllocationOrder order = new AllocationOrder();
        BeanUtils.copyProperties(po, order);
        order.setCommodities(commodities);
        order.setDocNo(CommonConstant.DB + baseMapper.getNextCode());
        // 新增调拨订单
        this.baseMapper.insert(order);
        for(AllocationOrderDetail detail : commodities){
            AllocationOrderDetail inDetail = new AllocationOrderDetail();
            BeanUtils.copyProperties(detail, inDetail);
            inDetail.setOrderId(order.getId());
            iAllocationOrderDetailService.insert(inDetail);
        }
        // 新增调拨入库单
        iAllocationInService.addIn(order);
        // 新增调拨出库单
        iAllocationOutService.addOut(order);
        return 1;
    }

    @Override
    public IPage<AllocationOrder> allocationList(AllocationOrderQueryPO po) {
        Page<AllocationOrder> page = new Page<>(po.getCurrent(), po.getSize());
        QueryWrapper<AllocationOrder> queryWrapper = new QueryWrapper<>();
        // 商品名模糊查询
        queryWrapper.like(StrUtil.isNotBlank(po.getInWarehouseNameLike()), "in_warehouse_name", po.getInWarehouseNameLike());
        // 仓库名模糊查询
        queryWrapper.like(StrUtil.isNotBlank(po.getOutWarehouseNameLike()), "out_warehouse_name", po.getOutWarehouseNameLike());
        if(ObjectUtil.isNotNull(po.getOrderTimeStart())){
            queryWrapper.gt( "create_time", DateUtil.beginOfDay(po.getOrderTimeStart()));
        }
        if(ObjectUtil.isNotNull(po.getOrderTimeEnd())){
            queryWrapper.lt( "create_time", DateUtil.endOfDay(po.getOrderTimeEnd()));
        }
        queryWrapper.orderByDesc("create_time");
        IPage<AllocationOrder> result = this.baseMapper.selectPage(page, queryWrapper);
        List<AllocationOrder> records = result.getRecords();
        if(CollectionUtil.isNotEmpty(records)){
            for (AllocationOrder ao : records){
                List<AllocationOrderDetail> details = iAllocationOrderDetailService.selectByOrderId(ao.getId());
                if(CollectionUtil.isNotEmpty(details)){
                    ao.setCommodities(details);
                }
            }
        }
        return result;
    }

    @Override
    public IPage<AllocationIn> allocationInList(AllocationOrderQueryPO po) {
        Page<AllocationIn> page = new Page<>(po.getCurrent(), po.getSize());
        QueryWrapper<AllocationIn> queryWrapper = new QueryWrapper<>();
        // 商品名模糊查询
        queryWrapper.like(StrUtil.isNotBlank(po.getInWarehouseNameLike()), "in_warehouse_name", po.getInWarehouseNameLike());
        // 仓库名模糊查询
        queryWrapper.like(StrUtil.isNotBlank(po.getOutWarehouseNameLike()), "out_warehouse_name", po.getOutWarehouseNameLike());
        if(ObjectUtil.isNotNull(po.getOrderTimeStart())){
            queryWrapper.gt( "create_time", DateUtil.beginOfDay(po.getOrderTimeStart()));
        }
        if(ObjectUtil.isNotNull(po.getOrderTimeEnd())){
            queryWrapper.lt( "create_time", DateUtil.endOfDay(po.getOrderTimeEnd()));
        }
        queryWrapper.orderByDesc("create_time");
        IPage<AllocationIn> result = iAllocationInService.getBaseMapper().selectPage(page, queryWrapper);
        List<AllocationIn> records = result.getRecords();
        if(CollectionUtil.isNotEmpty(records)){
            for (AllocationIn ao : records){
                List<AllocationInDetail> details = iAllocationInDetailService.selectByOrderId(ao.getId());
                if(CollectionUtil.isNotEmpty(details)){
                    ao.setCommodities(details);
                }
            }
        }
        return result;
    }

    @Override
    public IPage<AllocationOut> allocationOutList(AllocationOrderQueryPO po) {
        Page<AllocationOut> page = new Page<>(po.getCurrent(), po.getSize());
        QueryWrapper<AllocationOut> queryWrapper = new QueryWrapper<>();
        // 商品名模糊查询
        queryWrapper.like(StrUtil.isNotBlank(po.getInWarehouseNameLike()), "in_warehouse_name", po.getInWarehouseNameLike());
        // 仓库名模糊查询
        queryWrapper.like(StrUtil.isNotBlank(po.getOutWarehouseNameLike()), "out_warehouse_name", po.getOutWarehouseNameLike());
        if(ObjectUtil.isNotNull(po.getOrderTimeStart())){
            queryWrapper.gt( "create_time", DateUtil.beginOfDay(po.getOrderTimeStart()));
        }
        if(ObjectUtil.isNotNull(po.getOrderTimeEnd())){
            queryWrapper.lt( "create_time", DateUtil.endOfDay(po.getOrderTimeEnd()));
        }
        queryWrapper.orderByDesc("create_time");
        IPage<AllocationOut> result = iAllocationOutService.getBaseMapper().selectPage(page, queryWrapper);
        List<AllocationOut> records = result.getRecords();
        if(CollectionUtil.isNotEmpty(records)){
            for (AllocationOut ao : records){
                List<AllocationOutDetail> details = iAllocationOutDetailService.selectByOrderId(ao.getId());
                if(CollectionUtil.isNotEmpty(details)){
                    ao.setCommodities(details);
                }
            }
        }
        return result;
    }

    @Override
    public AllocationOrder  queryOrder(Long orderId) {
        AllocationOrder result = this.baseMapper.selectById(orderId);
        if(ObjectUtil.isNotNull(result)){
            List<AllocationOrderDetail> details = iAllocationOrderDetailService.selectByOrderId(result.getId());
            if(CollectionUtil.isNotEmpty(details)){
                result.setCommodities(details);
            }
        }
        return result;
    }

    @Override
    public AllocationIn queryInOrder(Long orderId) {
        AllocationIn result = iAllocationInService.getBaseMapper().selectById(orderId);
        if(ObjectUtil.isNotNull(result)){
            List<AllocationInDetail> details = iAllocationInDetailService.selectByOrderId(result.getId());
            if(CollectionUtil.isNotEmpty(details)){
                result.setCommodities(details);
            }
            List<OrderCost> orderCost = orderCostService.selectByMainId(orderId);
            result.setCosts(orderCost);
        }
        return result;
    }

    @Override
    public AllocationOut queryOutOrder(Long orderId) {
        AllocationOut result = iAllocationOutService.getBaseMapper().selectById(orderId);
        if(ObjectUtil.isNotNull(result)){
            List<AllocationOutDetail> details = iAllocationOutDetailService.selectByOrderId(result.getId());
            if(CollectionUtil.isNotEmpty(details)){
                result.setCommodities(details);
            }
            List<OrderCost> orderCost = orderCostService.selectByMainId(orderId);
            result.setCosts(orderCost);
        }
        return result;
    }


    public AllocationIn saveAllocationIn(AllocationInAddPO po) throws Exception {
        // 判断入库单是否存在及入库状态
        AllocationIn inOrder = iAllocationInService.getBaseMapper().selectById(po.getId());
        if(ObjectUtil.isNull(inOrder)){
            throw new Exception("入库单不存在");
        }
        if(ObjectUtil.isNotNull(inOrder.getState()) && inOrder.getState() == 1){
            throw new Exception("订单已入库");
        }
        inOrder.setRemark(po.getRemark());
        iAllocationInService.getBaseMapper().updateById(inOrder);
        List<AllocationOrderDetail> commodities = po.getCommodities();
        if(CollectionUtil.isNotEmpty(commodities)){
            for(AllocationOrderDetail detail : commodities){
                AllocationInDetail in = new AllocationInDetail();
                BeanUtils.copyProperties(detail, in);
                iAllocationInDetailService.insert(in);
            }
        }
        // 保存其他费用
        List<OrderCost> orderCosts = po.getCosts();
        // 保存其他费用
        if (CollectionUtils.isNotEmpty(orderCosts)){
            for(OrderCost oc : orderCosts){
                oc.setMainId(po.getId());
            }
            orderCostService.saveBatch(orderCosts);
        }
        return inOrder;
    }

    @Override
    public void submitAllocationIn(AllocationInAddPO po) throws Exception{
        AllocationIn order = saveAllocationIn(po);
        // todo 正式提交时，需要处理库存
        List<AllocationOrderDetail> commodities = po.getCommodities();
        if(CollectionUtil.isNotEmpty(commodities)){
            List<OrderCost> costs = po.getCosts();
            for(AllocationOrderDetail detail : commodities){
                BigDecimal inMoney = BigDecimal.ZERO;
                String agentName = order.getOutWarehouseName();
                String packageCost = "";
                String storageOrderNo = order.getDocNo();
                Products products = productsService.getById(detail.getCommodityId());
                if (products == null){
                    continue;
                }
                String specsName = null;
                if (ObjectUtil.isNotNull(detail.getSpecsId())){
                    ProductSpec productSpec = specService.getById(detail.getSpecsId());
                    specsName = productSpec.getName();
                }
                stockService.inStock(order.getOrderTime(), inMoney, products, detail.getSpecsId(), specsName, detail.getNumber(), detail.getWeight(), StockFlowType.ALLOCATION_IN.getValue(), order.getInWarehouseId(), order.getInWarehouseName(), agentName, packageCost, storageOrderNo, order.getId(), detail.getId(), BigDecimal.ZERO);
            }
        }
    }


    public int saveAllocationOut(AllocationOutAddPO po) throws Exception{
        // 判断入库单是否存在及入库状态
        AllocationOut outOrder = iAllocationOutService.getBaseMapper().selectById(po.getId());
        if(ObjectUtil.isNull(outOrder)){
            throw new Exception("出库单不存在");
        }
        if(ObjectUtil.isNotNull(outOrder.getState()) && outOrder.getState() == 1){
            throw new Exception("订单已出库");
        }
        outOrder.setRemark(po.getRemark());
        iAllocationOutService.getBaseMapper().updateById(outOrder);
        List<AllocationOrderDetail> commodities = po.getCommodities();
        if(CollectionUtil.isNotEmpty(commodities)){
            for(AllocationOrderDetail detail : commodities){
                AllocationOutDetail in = new AllocationOutDetail();
                BeanUtils.copyProperties(detail, in);
                iAllocationOutDetailService.insert(in);
            }
        }
        List<OrderCost> orderCosts = po.getCosts();
        // 保存其他费用
        if (CollectionUtils.isNotEmpty(orderCosts)){
            for(OrderCost oc : orderCosts){
                oc.setMainId(po.getId());
            }
            orderCostService.saveBatch(orderCosts);
        }
        return 1;
    }
    @Transactional
    @Override
    public void submitAllocationOut(AllocationOutAddPO po) throws Exception{
        saveAllocationOut(po);
        // 修改出库单状态，修改
        AllocationOut outOrder = new AllocationOut();
        outOrder.setId(po.getId());
        outOrder.setState(1);
        iAllocationOutService.getBaseMapper().updateById(outOrder);
        // 修改调拨单状态
        AllocationOrder order = new AllocationOrder();
        order.setId(po.getId());
        order.setOutStatus(0);
        this.baseMapper.updateById(order);
        // 正式提交时，需要处理库存
    }
    @Transactional
    @Override
    public void deleteOrder(Long id) throws Exception {
        AllocationOrder order = this.baseMapper.selectById(id);
        if(ObjectUtil.isNull(order)){
            throw new Exception("调拨订单不存在");
        }
        if(order.getOutStatus() == 0){
            throw new Exception("已经调拨出库，单据不能删除");
        }
        // 删除调拨订单
        this.baseMapper.deleteById(id);
    }
}
